#pragma once
#include"util.h"
#include<mutex>
#define HOST "127.0.0.1"
#define PORT 3306
#define USER "root"
#define PASS "147258Ll!"
#define DBNAME "gobang"

// id int primary key auto_increment,
//     username varchar(32) unique key not null,
//     password varchar(32) not null,
//     score int,
//     total_count int,
//     win_count int
class users_tables
{
public:
    MYSQL * _mysql;
    std::mutex _mutex;
public:
    users_tables()
    {
        _mysql=mysql_util::mysql_CREAT(HOST,USER,PASS,DBNAME,PORT);
        if(_mysql==nullptr)
        {
            ERR_Log("初始数据库句柄出错");
        }
        INF_Log("连接数据库成功");

        
    }
    ~users_tables()
    {
        mysql_util::mysql_destry(_mysql);
    }
     bool insert(Json::Value &user)
    {

        #define INSERT "insert into users values (null,'%s',password('%s'),1000,0,0);"
        char sql[4096]={0};
        
        if(user["username"].isNull()||user["password"].isNull())
        {
            ERR_Log("账号或密码为空");
            return false;
        }
        Json::Value root;
        // INF_Log("开始查询");
        bool ret=select_by_name(user["username"].asString(),root);
        
        if(ret==true)
        {
            ERR_Log("账号存在");
            return false;
        }
       
       
    sprintf(sql,INSERT,user["username"].asCString(),user["password"].asCString());
       bool ret1= mysql_util::mysql_exec(_mysql,sql);
        return true;
        
    }
    bool login(Json::Value &user)
    {
       if(user["username"].isNull()||user["password"].isNull())
        {
            ERR_Log("账号或密码为空");
            return false;
        }
        #define LOGIN "select id, score, total_count, win_count from users where username='%s'and password=password('%s');"
        char sql[4096];
        sprintf(sql,LOGIN,user["username"].asCString(),user["password"].asCString());
        MYSQL_RES *res=nullptr;
        std::unique_lock<std::mutex> lock(_mutex);
        int ret=mysql_util::mysql_exec(_mysql,sql);
         if(ret==false)
            {
                ERR_Log("执行%s语句出错",sql);
                return false;
            }
        res=mysql_store_result(_mysql);
        if(res==nullptr)
         {
            ERR_Log("读取结果出错");
            return false;
        } 
        if(mysql_num_rows(res)!=1)
        {
            ERR_Log("不存在该用户：%s",user["username"].asCString());
            return false;

        }
         MYSQL_ROW row = mysql_fetch_row(res);
         std::cout<<std::stoi(row[1])<<std::endl;
        
        user["id"] = (Json::UInt64)std::stol(row[0]);
       
        user["score"] = (Json::UInt64)std::stol(row[1]);
        
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);
        mysql_free_result(res);
        return true;


    }
    bool select_by_name(const std::string &name, Json::Value &user)
    {//select id, score, total_count, win_count from user where username='%s';
        #define SELECT_BYNAME "select id, score,total_count,win_count from users where username='%s';"
        char sql[4096]={0};
        sprintf(sql,SELECT_BYNAME,name.c_str());
        // INF_Log("%s",sql);
         MYSQL_RES *res = NULL;
         
        std::unique_lock<std::mutex> lock(_mutex);
           bool ret= mysql_util::mysql_exec(_mysql,sql);
           
            res=mysql_store_result(_mysql);
            if(res==NULL||mysql_num_rows(res)==0)
            {

                INF_Log("查询username:%s为空",name.c_str());
                 mysql_free_result(res);
                return false;
            }        
        
       
         int row_num=mysql_num_rows(res);
          
         MYSQL_ROW row = mysql_fetch_row(res);
          
        //  std::cout<<row[0]<<row[1]<<row[2]<<std::endl;
        //  std::cout<<row[3]<<std::endl;
         
        user["id"] = (Json::UInt64)std::stol(row[0]);
        
        user["username"] = name.c_str();
       
        user["score"] = (Json::UInt64)std::stol(row[1]);
        
        user["total_count"] = std::stoi(row[2]);
        
        user["win_count"] = std::stoi(row[3]);
        INF_Log("账号查询成功");
        mysql_free_result(res);
        return true;
       
    }
    bool select_by_id(uint64_t id, Json::Value &user)
    {
         #define SELECT_ID "select username, score, total_count, win_count from users where id=%ld;"
        char sql[4096]={0};
        sprintf(sql,SELECT_ID,id);
         MYSQL_RES *res = NULL;
         {
            std::unique_lock<std::mutex> lock(_mutex);
           int ret= mysql_util::mysql_exec(_mysql,sql);
           
            res=mysql_store_result(_mysql);
            if(res==nullptr||mysql_num_rows(res)!=1)
            {
                ERR_Log("查询id=%ld为空",id);
                 mysql_free_result(res);
                return false;
            } 
         }
         int row_num=mysql_num_rows(res);
        
         MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)id;
        user["username"] = row[0];
        user["score"] = (Json::UInt64)std::stol(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);
        mysql_free_result(res);
        return true;
       

    }
     bool win(uint64_t id)
     {
        Json::Value user;
        select_by_id(id,user);
        #define WIN "update users set score=score+30, total_count=total_count+1, win_count=win_count+1 where id=%ld;"
        char sql[4096]={0};
        sprintf(sql,WIN,id);
        int ret=mysql_util::mysql_exec(_mysql,sql);
         if (ret == false) {
                    ERR_Log("update lose user info failed!!\n");
                    return false;
               }
        return true;




     }
     bool lose(uint64_t id)
     {
        #define USER_LOSE "update users set score=score-30, total_count=total_count+1 where id=%ld;"
               char sql[4096] = {0};
               sprintf(sql, USER_LOSE, id);
               bool ret = mysql_util::mysql_exec(_mysql, sql);
               if (ret == false) {
                    ERR_Log("update lose user info failed!!\n");
                    return false;
               }
               return true;
     }

};